const { BrowserWindow, ipcMain,dialog,clipboard,shell } = require('electron');
import { exposeElectronAPI } from '@electron-toolkit/preload';
import { join } from 'path'
const axios = require('axios'); // 用于发送 HTTP 请求的库
const fs = require('fs');
const AdmZip = require('adm-zip');

const { execFile } = require('child_process'); // 用于执行命令行命令

const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
// const adapter = new FileSync(join(__dirname, 'database.db'));
const adapter = new FileSync('database.db');
const db = low(adapter);
db.defaults({local_table: []}).write();




// 窗口池数组
var winItems = []
// 主要进程窗口
var mainWin
// 是否初始化完成
var isInit


// webpreferences配置
class ConfigWebPreferences {
	nodeIntegration = true
	contextIsolation=false
	// devTools = false
	// webSecurity = false
	preload=join(__dirname, '../preload/index.js')// 如果需要预加载脚本
	sandbox=false
	// enableRemoteModule=true
	webSecurity=false
}

// 窗口配置
class ConfigWindow {
	//窗口是否可被用户手动最大化
	maximizable = false
	//窗口是否可被用户手动调整大小
	resizable = true
	center = true
	//显示边框
	frame = false
	//创建后不显示窗口
	show = false
	webPreferences = new ConfigWebPreferences()
	// model = true
	// parent = mainWin
	//fullscreenable = true
	// transparent = true
	// devTools=true

}

// 新建窗口
export class WindowPoolItem {
	constructor() {
		let config = new ConfigWindow()
		this.win = new BrowserWindow(config)
		this.param = null
		this.appInfo = null
		this.initEvent()
		this.loadUrl(this.win)
	}
	// 加载窗口
	async loadUrl(win) {
		let totalUrl = this.getTotalUrl()
		await win.loadURL(totalUrl)

		// await win.loadFile(totalUrl);
		/* //监听页面是否加载完成
		win.webContents.on('did-finish-load', () => {
			console.log('page load success');
			win.webContents.send('get-mini-program-info', `{"appId":202410281411,"appName":"鎶栭煶","logo":"../assets/images/logo.png","path":"pages/index/index"}`)
		}); */

		win.webContents.openDevTools();//打开调试工具
		//监听页面是否加载完成
		win.webContents.once('did-finish-load', () => {
			// console.log('page load success1');
			//告诉main.ts页面加载完成
			win.webContents.send('get-mini-program-info', this.param.data)

		});
	}
	// 根据环境变量拼接页面绝对地址并让窗口加载
	getTotalUrl() {
		/* if (process.env.NODE_ENV !== "production") {
			return `http://localhost:9080/#${url}`
		} else {
			return `file://${__dirname}/index.html#/${url}`
		} */

		return join(__dirname, '../renderer/src/mini_program/index.html')

		// return process.env['ELECTRON_RENDERER_URL']+`/child.html`;
	}
	// 初始化窗口事件
	initEvent() {

		/* // 窗口关闭事件
		this.win.on("close", () => {
			let survivalWindow=[];//存活窗口
			for (let i = 0; i < winItems.length; i++) {
				if (winItems[i].param && winItems[i].param.name == this.param.name) {
					winItems.splice(i, 1)
				}else{
					if(winItems[i].param){
						survivalWindow.push(winItems[i]);
					}
				}
			}
			console.log("survivalWindow:",winItems)
			//判断是否还有存活窗口,如果没有,则关闭所有窗口
			if(survivalWindow.length==0){
				// console.log("winItems:",winItems)
				console.log("winItems:",winItems.length)
				//关闭所有窗口
				winItems.forEach(item => {
					// console.log(item.win)
				    item.win.close()
				});

			}
		}) */
		
	}
	// 使用一个窗口
	use(windowParam) {
		this.effectParam(windowParam)
		this.loadUrl(this.win)
	}
	// 展示窗口
	effectParam(param) {
		this.param = param

		//当前窗口是否始终在其它窗口之前
		// this.win.setAlwaysOnTop(true)

		try {
			this.controlSize()
		} catch (error) {
		    
		}

		//无论焦点如何, 将窗口移至顶端
		this.win.moveTop()

		// this.win.center();

		!isInit && (this.win.show())
	}
	// 设置窗口大小等相关配置
	controlSize() {
		//为每个窗口设置不同的appId后,单独显示在任务栏中
		this.win.setAppDetails({
			appId: 'win_'+Date.now()
		});

		//设置窗口大小
		if (this.param.size) {
			this.win.setSize(this.param.size.width, this.param.size.height)
		}
		//保存小程序的信息到窗口对象中
		this.appInfo = JSON.parse(this.param.data);
		
		let logoIcon=join(process.cwd(), '/apps/'+this.appInfo.appid+'/icon.png');
		//判断logo是否存在
		if (!fs.existsSync(logoIcon)) {
			//默认图标
			logoIcon=join(process.cwd(), '/resources/images/mini_apps_logo.png');
		}
		//设置窗口图标
		this.win.setIcon(logoIcon)

		// 示例：延迟1秒后设置窗口标题
		setTimeout(() => {
			//设置窗口标题
			this.win.setTitle(this.appInfo.name);
		}, 1000);

		/* if (this.param.resizable === false) {
			this.win.setResizable(false)
			if (this.param.fullscreen) {
				this.win.setFullScreen(true)
				// console.log("是否全屏", this.win.isFullScreen());
			}
			return
		} else if (this.param.minSize) {
			this.win.setMinimumSize(this.param.minSize.width, this.param.minSize.height)
			this.win.setResizable(true)
			return
		}
		this.win.setResizable(true)
		this.win.setMinimumSize(200, 150) */
	}
}


export class InitWindowPool {
	constructor(mainWindow) {
		// 初始化窗口池
		this.winItems = winItems
		isInit = true
		mainWin = mainWindow
		this.init()
	}
	init() {
		// 初始化三个窗口
		for (let i = 0; i < 3; i++) {
			winItems.push(new WindowPoolItem())
		}

		// 打开小程序窗口
		ipcMain.on('open-mini-app-window', (e, data) => {
			const appInfo = JSON.parse(data);
			// 子窗口配置数据
			let winConfigJson = {
				name: appInfo.appid,
				size: {width: Number(appInfo.window_width),height: Number(appInfo.window_height),},
				//参数
				data: data
			}
			let param = winConfigJson;
			// 已有窗口则直接展示,没有则新建一个
			if (!this.isWindowInUse(param)){
				this.picAndUse(param)
			}
		});

		//最小化小程序当前子窗口
		ipcMain.on('current-window-minimize', (_event, appId) => {

			this.curWin(appId).minimize();

		})

		/*
			// 放大
			ipcMain.on(name + '-max', e => {
				if (this.curWin(name).isMaximized()) {
					this.curWin(name).restore()
				} else {
					this.curWin(name).maximize()
				}
			})
		*/

		//关闭小程序当前子窗口
		ipcMain.on('current-window-close', (_event, appId) => {

			let currentWin=this.curWin(appId);
			currentWin.hide();
			// currentWin.close();//关闭窗口

			let survivalWindow=[];//存活窗口
			for (let i = 0; i < winItems.length; i++) {
				if (winItems[i].param && winItems[i].param.name == appId) {
					if(winItems.length>4){
						winItems.splice(i, 1)
					}
				}else{
					//存活窗口
					if(winItems[i].param){
						survivalWindow.push(winItems[i]);
					}
				}
			}
			//判断是否还有存活窗口,如果没有,则关闭所有窗口
			if(survivalWindow.length==0){
				if(mainWin.isDestroyed()){
					//关闭所有窗口
					winItems.forEach(item => {
						item.win.close()
					});
					winItems=[];//清空窗口
					survivalWindow=[];//清空存活窗口
				}
			}else{
				//窗口是否可见的
				let winShowItem=[];
				//判断存活窗口是否都隐藏如果都隐藏就关闭所有的窗口
				survivalWindow.forEach(item => {
					if (item.win.isVisible()) {
						//窗口是可见的
						winShowItem.push(item);
					}
				});
				if(winShowItem.length==0){
					if(mainWin.isDestroyed()){
						//关闭所有窗口
						winItems.forEach(item => {
							item.win.close()
						});
						winItems=[];//清空存活窗口
						winShowItem=[];
					}
				}

			}
		})

		//下载源码文件
		ipcMain.on('down-file', (_event, opts) => {

			this.winItems.every(async (v) => {
				if (v.param && v.param.name === opts.appId) {

					let res=await axios({url:opts.url,method:'POST',data:{appId:opts.appId},responseType: 'arraybuffer',headers:{token:opts.token}});
					const str = res.headers['content-disposition']
					if (!res || !str) {
						error(res.message || '下载失败！')
						return
					}

					if (res && res.status === 200 && res.data) {
						// 保存文件的本地路径
						const localFilePath = 'apps/'+opts.appId+'.zip';
						const extractPath = 'apps/'+opts.appId;					
						// 将 arraybuffer 转换为 Buffer
						const buffer = Buffer.from(res.data, 'binary');
	
						// 将 Buffer 写入文件
						fs.writeFileSync(localFilePath, buffer);
	
						// 确保目标目录存在
						if (!fs.existsSync(extractPath)) {
							fs.mkdirSync(extractPath, { recursive: true });
						}
	
						// 创建一个新的 AdmZip 实例
						const zip = new AdmZip(localFilePath);
	
						// 解压 ZIP 文件到指定目录
						zip.extractAllTo(extractPath, true);

						v.win.webContents.send('down-file-success');

						// 删除源码压缩包文件
						fs.unlinkSync(localFilePath);

						return false;

					} else {
						console.log('下载失败！',res)
						if((res.data.data.code === 1001 || res.data.data.code === 1003) || !opts.noRefetch){
							v.win.webContents.send('refresh-token');
						}else{
							error(res.message || '下载失败！')
						}
					}
				    
				}
			})
		});
		//获取app的配置信息
		ipcMain.on('read-config-file', (_event,opts) => {
			this.winItems.every((v) => {
				if (v.param && v.param.name === opts.appId) {
					let result=fs.readFileSync('apps/'+opts.appId+'/compileResult.json', 'utf-8')
					v.win.webContents.send('config-info', result);
					return false
				}
			});
		});
		
		//监听调用系统api模块消息
		ipcMain.on("sys-api-message", async (_event, opts)=> {
			// console.log("sys-api-message:",opts)
			const {messageId,type, data} = opts;
			let result='';
			switch (type) {
				case "writeFilec":
					//写入文件
					result=fs.writeFileSync(data.file, data.content, 'utf-8');
					break;
				case "readFile":
					//读取文件
					result=fs.readFileSync(data.file, 'utf-8');
					break;
				case "exists":
					//检查文件,文件夹是否存在
					result=fs.existsSync(data.file)
					break;
				case "homeDir":
					// 获取当前用户的主目录
					const userHomeDir = os.homedir();
					result=userHomeDir;
					break;
				case "setStorage":
					// 查询单条数据
					let localTableData=db.get('local_table').find({ key: data.key }).value();
					if(!localTableData){
						// 插入单条数据
						db.get('local_table').push({ key: data.key, value: data.value }).write();
					}else{
						// 更新单条数据
						db.get('local_table').find({ key: data.key }).assign({ value: data.value }).write();
					}
					break;
				case "getStorage":
					// 查询单条数据
					let localData=db.get('local_table').find({ key: data.key }).value();
					result=localData?localData.value:'';
					break;
				case "removeStorage":
					// 删除单条数据
					db.get('local_table').remove({ key: data.key }).write();
					break;
				case "clearStorage":
					// 删除表中所有数据
					db.get('local_table').remove().write();
					break;
				case "openDialog":
					result = await dialog.showOpenDialog(mainWindow, {
						title : "选择项目",
						properties: ['openDirectory']
					});
					break;
				case "setClipboardData":
					if(data.type === 'text'){
						clipboard.writeText(data.data);
					}else if(data.type === 'image'){
						const imageBuffer = fs.readFileSync(data.data);
  						clipboard.writeImage(imageBuffer);
					}
					break;
				case "getClipboardData":
					if(data.type === 'text'){
						result=clipboard.readText();
					}else if(data.type === 'image'){
						const image = clipboard.readImage();
						if (!image.isEmpty()) {
						  image.toPNG((err, png) => {
							if (err) throw err;
							fs.writeFileSync(data.outputPath, png);
						  });
						}
					}
					break;
				case "openExternalFile":
					if(data.type === 'exe'){
						execFile(data.path, [], (error, stdout, stderr) => {
							if (error) {
							  console.error(`执行出错: ${error.message}`);
							  return;
							}
							if (stderr) {
							  console.error(`stderr: ${stderr}`);
							  return;
							}
						});
					}else if(data.type === 'url'){
						shell.openExternal(data.url)
					}
					break;

				default:
			}
			mainWindow.webContents.send("on-sys-api-message",{messageId,result});
		});

		isInit = false
	}

	// 已有窗口则直接展示
	isWindowInUse(param) {
		// 使用 find 方法查找符合条件的对象
		let item = winItems.find((v) => v.param && v.param.name === param.name)
		if (!item) return false
		item.effectParam(param)
		return true
	}
	// 当前窗口
	curWin(name) {
		return winItems.find((v) => v.param && v.param.name === name).win
	}
	// 使用一个窗口并创建一个新的
	picAndUse(param) {
		//没有param属性的，就是没用过的窗口
		let item = winItems.find((v) => !v.param)
		// 使用一个窗口
		item.use(param)
		winItems.push(new WindowPoolItem())
	}
}

